package com.myk.game.gobangchess.rooms.oldrooms;

import com.myk.game.gobangchess.CustomBottom;
import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.Msger;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.AbsDiffViewChessRoom;
import com.myk.game.gobangchess.rooms.absrooms.movechess.MoreColorCost;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.utils.Pair;

import java.util.ArrayList;
import java.util.List;

/**
 * 双命传入象棋（已经合并到单命模式中了，所以这个隐藏掉）
 *
 */
public class AfferentTwoLiveChessRoom extends AbsDiffViewChessRoom {

    private CacheSign chessBoardCacheSign; //背景缓存标记
    private CacheSign detentionPlatCacheSign; //拘台缓存标记
    private final List<int[]> moveArrayList = new ArrayList<>(); // 棋子移动标记
    private List<Chess> chessList; //场上棋子集合
    private Sider blackSider; //游戏黑方实体
    private Sider whiteSider; //游戏白方实体

    public AfferentTwoLiveChessRoom(String roomName) {
        super(roomName, "传入象棋再进化!将帅有两条命。", "双命传入象棋", GridsUtils.createEmptyGrids(10, 9), true, true);
        initChessBoardCacheSign();
        initDetentionPlatCacheSign();
    }

    //棋盘背景的设计
    private void initChessBoardCacheSign() {
        List<Sign> chessboardStyle = new ArrayList<>();
        //背景
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), MoreColorCost.BOARD_BACKGROUND, MoreColorCost.BOARD_BACKGROUND, 1.8f, 0, 0));
        //边框
        chessboardStyle.add(getPath(0, 0, 0, 8, 2, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPath(9, 0, 9, 8, 2, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPath(0, 0, 9, 0, 2, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPath(0, 8, 9, 8, 2, MoreColorCost.BOARD_LINE));
        //线条
        for (int i = 1; i < 9; i++) {
            chessboardStyle.add(getPath(i, 0, i, 8, 1, MoreColorCost.BOARD_LINE));
        }
        for (int i = 1; i < 8; i++) {
            chessboardStyle.add(getPath(0, i, 4, i, 1, MoreColorCost.BOARD_LINE));
            chessboardStyle.add(getPath(5, i, 9, i, 1, MoreColorCost.BOARD_LINE));
        }
        //斜线条
        chessboardStyle.add(getPathDia(0, 3, 2, 5, 1, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPathDia(0, 5, 2, 3, 1, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPathDia(9, 3, 7, 5, 1, MoreColorCost.BOARD_LINE));
        chessboardStyle.add(getPathDia(9, 5, 7, 3, 1, MoreColorCost.BOARD_LINE));
        //青筋
        List<Integer> veinIndexes = new ArrayList<>();
        veinIndexes.add(getIndex(2, 1));
        veinIndexes.add(getIndex(2, 7));
        veinIndexes.add(getIndex(3, 2));
        veinIndexes.add(getIndex(3, 4));
        veinIndexes.add(getIndex(3, 6));
        veinIndexes.add(getIndex(7, 1));
        veinIndexes.add(getIndex(7, 7));
        veinIndexes.add(getIndex(6, 2));
        veinIndexes.add(getIndex(6, 4));
        veinIndexes.add(getIndex(6, 6));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(veinIndexes, MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 1, 1, 1));
        List<Integer> vein2Indexes = new ArrayList<>();
        vein2Indexes.add(getIndex(3, 0));
        vein2Indexes.add(getIndex(6, 0));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(vein2Indexes, MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 0, 1, 1, 0));
        List<Integer> vein3Indexes = new ArrayList<>();
        vein3Indexes.add(getIndex(3, 8));
        vein3Indexes.add(getIndex(6, 8));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(vein3Indexes, MoreColorCost.BOARD_LINE).setCompAngle(0, 0, 0, 0, 1, 0, 0, 1));

        //楚河汉界
        chessboardStyle.add(new TitleSign(0.25f, 0.5f, 0, "楚  河", MoreColorCost.BOARD_LINE, 0.5f));
        chessboardStyle.add(new TitleSign(0.75f, 0.5f, 0, "汉  界", MoreColorCost.BOARD_LINE, 0.5f));
        //添加到缓存标记
        chessBoardCacheSign = new CacheSign(this, "chessBoardCacheSign", 3, true, chessboardStyle); //*** 修改背景样式记得改这里的版本号！！！
    }

    //拘台背景的设计
    private void initDetentionPlatCacheSign() {
        List<Sign> chessboardStyle = new ArrayList<>();
        //背景
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), MoreColorCost.BOARD_BACKGROUND, MoreColorCost.BOARD_BACKGROUND, 1.8f, 0, 0));
        //虚化背景
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), "#99BEB2B3", "#99BEB2B3", 1.8f, 0, 0));
        //边框
        chessboardStyle.add(getPath(0, 0, 0, 8, 2, "#9945465E"));
        chessboardStyle.add(getPath(9, 0, 9, 8, 2, "#9945465E"));
        chessboardStyle.add(getPath(0, 0, 9, 0, 2,"#9945465E"));
        chessboardStyle.add(getPath(0, 8, 9, 8, 2, "#9945465E"));
        //线条
        for (int i = 1; i < 9; i++) {
            chessboardStyle.add(getPath(i, 0, i, 8, 1, "#9945465E"));
        }
        for (int i = 1; i < 8; i++) {
            chessboardStyle.add(getPath(0, i, 4, i, 1, "#9945465E"));
            chessboardStyle.add(getPath(5, i, 9, i, 1, "#9945465E"));
        }
        //斜线条
        chessboardStyle.add(getPathDia(0, 3, 2, 5, 1, "#9945465E"));
        chessboardStyle.add(getPathDia(0, 5, 2, 3, 1, "#9945465E"));
        chessboardStyle.add(getPathDia(9, 3, 7, 5, 1, "#9945465E"));
        chessboardStyle.add(getPathDia(9, 5, 7, 3, 1, "#9945465E"));
        //青筋
        List<Integer> veinIndexes = new ArrayList<>();
        veinIndexes.add(getIndex(2, 1));
        veinIndexes.add(getIndex(2, 7));
        veinIndexes.add(getIndex(3, 2));
        veinIndexes.add(getIndex(3, 4));
        veinIndexes.add(getIndex(3, 6));
        veinIndexes.add(getIndex(7, 1));
        veinIndexes.add(getIndex(7, 7));
        veinIndexes.add(getIndex(6, 2));
        veinIndexes.add(getIndex(6, 4));
        veinIndexes.add(getIndex(6, 6));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(veinIndexes, "#9945465E").setCompAngle(0, 0, 0, 0, 1, 1, 1, 1));
        List<Integer> vein2Indexes = new ArrayList<>();
        vein2Indexes.add(getIndex(3, 0));
        vein2Indexes.add(getIndex(6, 0));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(vein2Indexes, "#9945465E").setCompAngle(0, 0, 0, 0, 0, 1, 1, 0));
        List<Integer> vein3Indexes = new ArrayList<>();
        vein3Indexes.add(getIndex(3, 8));
        vein3Indexes.add(getIndex(6, 8));
        chessboardStyle.add(FigureSign.makeBatchSingleFigure(vein3Indexes, "#9945465E").setCompAngle(0, 0, 0, 0, 1, 0, 0, 1));

        //楚河汉界
        chessboardStyle.add(new TitleSign(0.25f, 0.5f, 0, "拘  台", "#9945465E", 0.5f));
        chessboardStyle.add(new TitleSign(0.75f, 0.5f, 0, "俘  虏", "#9945465E", 0.5f));

        //添加到缓存标记
        detentionPlatCacheSign = new CacheSign(this, "detentionPlatCacheSign", 5, true, chessboardStyle);//*** 修改背景样式记得改这里的版本号！！！
    }

    //棋盘背景路径绘制方法
    public PathSign getPath(final int fRow, final int fCol, final int tRow, final int tCol, final float size, String color) {
        List<Pair<Integer, Integer>> nodes = new ArrayList<>();
        nodes.add(new Pair<>(getIndex(fRow, fCol), 4));
        nodes.add(new Pair<>(getIndex(tRow, tCol), 4));
        return new PathSign(nodes, color, color, size, 0);
    }

    //棋盘背景斜线路径绘制方法
    public PathSign getPathDia(final int fRow, final int fCol, final int tRow, final int tCol, final float size, String color) {
        List<Pair<Integer, Integer>> nodes = new ArrayList<>();
        nodes.add(new Pair<>(getIndex(fRow, fCol), 4));
        nodes.add(new Pair<>(getIndex(tRow, tCol), 4));
        return new PathSign(nodes, color, color, size, 1);
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        if (cacheName.equals("detentionPlatCacheSign")) {
            return detentionPlatCacheSign;
        }
        else if (cacheName.equals("chessBoardCacheSign")) {
            return chessBoardCacheSign;
        }
        return chessBoardCacheSign;
    }

    @Override
    public String getRuleText() {
        return "《传入象棋》\n" +
                "以象棋为基础，增加“传递”和“打入”两种玩法。\n" +
                "一、“传递”\n" +
                "走子时，可以把棋子A走到本方另一个棋子B的上面，并按照B的“吃法”，把A移动到另一个空位，不能是A的原来位置。\n" +
                "特殊的，象不能被传递过河，士和将不能被传递出九宫。\n" +
                "二、“打入”\n" +
                "吃掉的对方棋子，会变成我方棋子，放入驹台。\n" +
                "此后，可以花一步棋，把驹台里的棋子，放到本方任一个棋子C的上面，并按照C的“吃法”，移动到一个空位。\n" +
                "特殊的，士和象在打入时，不能停留在本方半场;\n" +
                "士和象在打入后，也不能走回本方半场。\n" +
                "三、将帅有两条命，第一个杀对方将帅的棋子会反被吃，且不作为对方的持驹，同时对方将帅命数减一，之后再杀对方将帅一次就赢棋。\n" +
                "特殊的，禁止将帅照面。";
    }

    @Override
    public String getCoordMode() {
        return "05040000";
    }

    @Override
    public int getCountdownSec() {
        return 180; //传入象棋思考时间比较长，改成300s吧
    }

    @Override
    public String getGameInfo(int viewPoint) {
        //先清空棋盘
        signList.clear();
        //三种身份各自视角的自定义绘制
        if (viewPoint == 1) {
            blackSider.render();
        }
        else if (viewPoint == 2) {
            whiteSider.render();
        }
        else {
            publicRender();
        }
        return super.getGameInfo();
    }

    //公共渲染
    public void publicRender() {
        //画棋盘背景
        signList.add(chessBoardCacheSign);
        //绘制场上棋子
        renderChessList();
        //绘制双方的俘虏预览
        renderCaptiveListPreview();
        //绘制移动箭头
        renderMoveArray();
    }

    //遍历绘制场上棋子
    public void renderChessList() {
        curGrids = GridsUtils.copyGrids(originGrids);
        if (chessList != null) {
            for (Chess piece : chessList) {
                curGrids[piece.row][piece.col] = piece.side; //显示棋子的底座
                signList.add(new TextSign(getIndex(piece.row, piece.col), piece.name, piece.side == 1 ? ColorCost.WHITE : ColorCost.BLACK)); //绘制棋子外观
                if (piece instanceof General){
                    signList.add(new BadgeSign(getIndex(piece.row, piece.col), piece.side == 1 ? String.valueOf(blackSider.hp) : String.valueOf(whiteSider.hp), 0, ColorCost.NEW_PUT_POINT, piece.side == 1 ? ColorCost.BLACK:ColorCost.WHITE));
                }
            }
        }
    }

    //绘制双方俘虏预览
    public void renderCaptiveListPreview() {
        if (blackSider != null && whiteSider != null) {
            float leftX = 1+(0.3f)/curGrids[0].length; //左列位置 棋盘终点再偏移3/10单位格子
            float rightX = 1+(0.7f)/curGrids[0].length; //右列位置 棋盘终点再偏移7/10单位格子
            float blackTop = (0.5f) / curGrids.length; //黑方预览顶部位置
            float whiteTop = 1 - (0.5f) / curGrids.length; //白方预览顶部位置 （白方是从下往上绘制的）
            float paddingY = 0.0155f / curGrids.length; //因为预览棋子底座和文字大小不同，所以需要做padding，让文字正好显示在底座中心
            float unitH = 0.5f / curGrids.length; //行距定为半个格子
            List<Chess> blackPreviewList = new ArrayList<>(blackSider.captiveList);
            if (blackSider.outside!=null){
                blackPreviewList.add(blackSider.outside);
            }
            for (int i = 0; i < blackPreviewList.size(); i++) {
                int j = i/2; //形成书写文字的排列效果每行两列
                float bClipY = blackTop + j * unitH;
                if (blackPreviewList.get(i) == blackSider.outside){
                    signList.add(new TitleSign(i % 2 == 0?leftX:rightX, bClipY, 0, "●", ColorCost.BLACK, 0.35f));
                    signList.add(new TitleSign(i % 2 == 0?leftX:rightX, bClipY  + paddingY , 0, blackSider.outside.name, ColorCost.WHITE, 0.25f));
                }
                else {
                    signList.add(new TitleSign(i % 2 == 0?leftX:rightX, bClipY, 0, "●", ColorCost.WHITE, 0.35f));
                    signList.add(new TitleSign(i % 2 == 0?leftX:rightX, bClipY  + paddingY , 0, blackPreviewList.get(i).name, ColorCost.BLACK, 0.25f));
                }
            }
            List<Chess> whitePreviewList = new ArrayList<>(whiteSider.captiveList);
            if (whiteSider.outside!=null){
                whitePreviewList.add(whiteSider.outside);
            }
            for (int i = 0; i < whitePreviewList.size(); i++) {
                int j = i/2;
                float wClipY = whiteTop - j * unitH;
                if (whitePreviewList.get(i) == whiteSider.outside){
                    signList.add(new TitleSign(i % 2 == 0?leftX:rightX, wClipY, 0, "●", ColorCost.WHITE, 0.35f));
                    signList.add(new TitleSign(i % 2 == 0?leftX:rightX, wClipY  + paddingY, 0, whiteSider.outside.name, ColorCost.BLACK, 0.25f));
                }
                else {
                    signList.add(new TitleSign(i % 2 == 0?leftX:rightX, wClipY, 0, "●", ColorCost.BLACK, 0.35f));
                    signList.add(new TitleSign(i % 2 == 0?leftX:rightX, wClipY  + paddingY, 0, whitePreviewList.get(i).name, ColorCost.WHITE, 0.25f));
                }
            }
        }
    }

    //绘制移动箭头
    public void renderMoveArray() {
        for (int[] moveArray : moveArrayList) {
            signList.add(new LineSign(moveArray[0], moveArray[1], ColorCost.MOVE_ARROW_LIGHT, 1));
        }
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        moveArrayList.clear();
        chessList = null;
        blackSider = null;
        whiteSider = null;
    }

    @Override
    protected void onStartPrepare() {
        //初始化场上棋子
        initChessList();
        //初始化对弈双方状态
        blackSider = new Sider(this, 1);
        whiteSider = new Sider(this, 2);
        noticeBlackMove(); //默认通知黑方先行动
    }

    @Override
    protected void prepareInGameButtons() {
        //绑定切换拘台按钮
        if (player_black != player_white) {
            player_black.registerCustomBottom(new CustomBottom(this, "切换拘台", p -> blackSider.switchPlat()));
            player_white.registerCustomBottom(new CustomBottom(this, "切换拘台", p -> whiteSider.switchPlat()));
        }
        else {
            player_black.registerCustomBottom(new CustomBottom(this, "切换拘台", p -> {
                if (cur == 1) blackSider.switchPlat();
                else if (cur == 2) whiteSider.switchPlat();
            }));
        }
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (value == 1) {
            blackSider.doRule(row, col);
        }
        else if (value == 2) {
            whiteSider.doRule(row, col);
        }
    }

    //初始化棋子列表
    private void initChessList() {
        chessList = new ArrayList<>();
        // 兵
        chessList.add(new Pawn(this, "兵",1, 3, 0));
        chessList.add(new Pawn(this, "兵",1, 3, 2));
        chessList.add(new Pawn(this, "兵",1, 3, 4));
        chessList.add(new Pawn(this, "兵",1, 3, 6));
        chessList.add(new Pawn(this, "兵",1, 3, 8));
        chessList.add(new Pawn(this, "卒",2, 6, 0));
        chessList.add(new Pawn(this, "卒",2, 6, 2));
        chessList.add(new Pawn(this, "卒",2, 6, 4));
        chessList.add(new Pawn(this, "卒",2, 6, 6));
        chessList.add(new Pawn(this, "卒",2, 6, 8));
        // 炮
        chessList.add(new Cannon(this, "炮",1, 2, 1));
        chessList.add(new Cannon(this, "炮",1, 2, 7));
        chessList.add(new Cannon(this, "砲",2, 7, 1));
        chessList.add(new Cannon(this, "砲",2, 7, 7));
        // 车
        chessList.add(new Chariot(this, "車",1, 0, 0));
        chessList.add(new Chariot(this, "車",1, 0, 8));
        chessList.add(new Chariot(this, "车",2, 9, 0));
        chessList.add(new Chariot(this, "车",2, 9, 8));
        // 马
        chessList.add(new Horse(this, "馬",1, 0, 1));
        chessList.add(new Horse(this, "馬",1, 0, 7));
        chessList.add(new Horse(this, "马",2, 9, 1));
        chessList.add(new Horse(this, "马",2, 9, 7));
        // 象
        chessList.add(new Bishop(this, "相",1, 0, 2));
        chessList.add(new Bishop(this, "相",1, 0, 6));
        chessList.add(new Bishop(this, "象",2, 9, 2));
        chessList.add(new Bishop(this, "象",2, 9, 6));
        // 士
        chessList.add(new Guard(this, "仕",1, 0, 3));
        chessList.add(new Guard(this, "仕",1, 0, 5));
        chessList.add(new Guard(this, "士",2, 9, 3));
        chessList.add(new Guard(this, "士",2, 9, 5));
        // 帅
        chessList.add(new General(this, "帅",1, 0, 4));
        chessList.add(new General(this, "将",2, 9, 4));
    }

    //检测胜负
    public void checkOver() {
        stepAdd();
        //胜负判断有点复杂，暂时只判断是否吃掉对方的帅
        if (hasChessType(blackSider.captiveList, General.class)) {
            doOver(WinMode.BLACK_WIN, "黑方获胜！");
            return;
        }
        else if (hasChessType(whiteSider.captiveList, General.class)) {
            doOver(WinMode.WHITE_WIN, "白方获胜！");
            return;
        }
        //++还要判断是否无棋可走
        //++还要判断是否长将循环
        changeNoticeMove();//切换行动方
    }

    //切换行动方
    public void changeNoticeMove() {
        if (cur == 1) {
            noticeWhiteMove();
        }
        else {
            noticeBlackMove();
        }
    }

    //根据坐标搜索棋子 （有多个棋子时取城门之上的棋子, 可为空）
    public Chess getChessByPos(int row, int col) {
        for (Chess chess : chessList) {
            if (chess.row == row && chess.col == col) {
                return chess;
            }
        }
        return null;
    }

    //根据index搜索棋子 （有多个棋子时取城门之上的棋子, 可为空）
    public Chess getChessByIndex(int index) {
        for (Chess chess : chessList) {
            if (chess.getIndex() == index) {
                return chess;
            }
        }
        return null;
    }

    //检测棋子集合中是否包含某个类型的棋子
    public boolean hasChessType(List<Chess> list, Class<? extends Chess> chessType) {
        for (Chess chess : list) {
            if (chess.getClass() == chessType) {
                return true;
            }
        }
        return false;
    }

    //判断将帅是否照面
    private boolean checkKingFaceKing() {
        for (Chess chess : chessList) {
            if (chess instanceof General){
                // 白脸杀
                List<Integer> eatRange = chess.getEatRange();
                for (int index : eatRange) {
                    if (getChessByIndex(index) instanceof General) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    //检测坐标位置是否在黑方半区
    public int getBoardSideByPos(int row, int col) {
        if (col >=0 && col < curGrids[0].length){
            if (row>=0 && row < curGrids.length / 2){
                return 1;
            }
            else if (row>curGrids.length / 2 && row < curGrids.length){
                return 2;
            }
        }
        return 0;
    }

    /**
     * 对弈双方的各种信息
     */
    private static class Sider {

        public AfferentTwoLiveChessRoom room;
        private final int side;//归属黑棋还是白棋 1黑  2白
        private boolean isOpenPlat; //是否展开了拘台显示
        private int hp; //当前王的剩余生命值
        private final List<Chess> captiveList; //俘虏棋子集合
        private Chess outside; //移除棋盘外的棋子
        private Chess choose; //当前选中的场上棋子
        private Chess captive; //当前选中的持拘棋子
        private Chess transfer; //当前选中的传送台

        public Sider(AfferentTwoLiveChessRoom room, int side) {
            this.room = room;
            this.side = side;
            this.captiveList = new ArrayList<>();
            this.hp = 2;
        }

        //私有独立界面渲染
        public void render() {
            //拘台打开状态显示拘台
            if (isOpenPlat) {
                //画拘台相关私有画面
                renderDetentionPlat();
                //绘制双方的俘虏预览
                room.renderCaptiveListPreview();
            }
            //拘台关闭状态显示棋盘
            else {
                //画棋盘背景、场上棋子、俘虏预览、移动路径等公共画面
                room.publicRender();
                //场上棋子选中效果等私有画面
                if (choose != null) {
                    renderChessChoose();
                }
                else if (captive != null){
                    renderCaptiveChoose();
                }
            }
        }

        //拘台的绘制
        private void renderDetentionPlat() {
            //画拘台遮罩背景
            room.signList.add(room.detentionPlatCacheSign);
            //遍历绘制拘台棋子
            room.curGrids = GridsUtils.copyGrids(room.originGrids);
            for (int i = 0; i < captiveList.size(); i++) {
                Chess chess = captiveList.get(i);
                //棋子绘制的位置根据在captiveList中的位置来
                int cR = room.curGrids.length - 2 - (i / 7);
                int cC = i % 7 + 1;
                room.curGrids[cR][cC] = chess.side; //显示棋子的底座
                chess.row = cR; //正常不该在这里修改棋子状态的，但是可以解决选中俘虏时根据坐标逆运算棋子索引的代码，并且我确保这里不会导致其它bug
                chess.col = cC;
                room.signList.add(new TextSign(room.getIndex(cR, cC), chess.name, chess.side == 1 ? ColorCost.WHITE : ColorCost.BLACK)); //绘制棋子外观
                //画拘台持拘棋子选中效果
                if (captive != null && captive == chess) {
                    room.signList.add(new GroundSign(room.getIndex(cR, cC), "#00FFFFFF", "#FF33CC33", 2F, 0, 1));
                }
            }
        }

        //当前选中棋子的绘制
        private void renderChessChoose() {
            //未选取传送台时
            if (transfer == null){
                //画选中绿框
                room.signList.add(new GroundSign(choose.getIndex(), "#00FFFFFF", "#FF33CC33", 2F, 0, 1));
                //画一下可移动范围
                for (Integer index : choose.getMoveRange()) {
                    room.signList.add(new ColorSign(index, MoreColorCost.MOVE));
                }
                //画一下吃子范围
                for (Integer index : choose.getEatRange()) {
                    room.signList.add(new ColorSign(index, MoreColorCost.EAT));
                }
                //画一下可选传送台的范围
                for (Integer index : choose.getTransferRange()) {
                    room.signList.add(new ColorSign(index, MoreColorCost.MOVE));
                }
            }
            //选择了传送台时
            else {
                //选中棋子原位置禁止传入
                room.signList.add(new ColorSign(choose.getIndex(), "#66EE6666"));
                //选中棋子以角标形式显示在传送台上
                room.signList.add(new BadgeSign(transfer.getIndex(), choose.name, 2, ColorCost.WHITE, ColorCost.BLACK));
                //绘制可选的传入位置
                for (Integer index : transfer.getAfferentRange(choose)) {
                    room.signList.add(new ColorSign(index, MoreColorCost.EAT));
                }
            }
        }

        //当前选中俘虏棋子的绘制
        private void renderCaptiveChoose() {
            //待选打入传送台时的绘制
            if (transfer == null){
                for (Chess chess : room.chessList) {
                    if (chess.side == side){
                        room.signList.add(new ColorSign(chess.getIndex(), MoreColorCost.MOVE));
                    }
                }
            }
            //已经选择了打入传送台时的绘制
            else {
                //打入棋子以角标形式显示在传送台上
                room.signList.add(new BadgeSign(transfer.getIndex(), captive.name, 2, ColorCost.BLACK, ColorCost.WHITE));
                //绘制可选的打入位置
                for (Integer index : transfer.getPutRange(captive)) {
                    room.signList.add(new ColorSign(index, MoreColorCost.EAT));
                }
            }
        }

        //切换拘台显示
        public void switchPlat() {
            this.isOpenPlat = !isOpenPlat;
            room.noticeAllRefreshGameInfo();
        }

        //私有独立交互逻辑处理
        public void doRule(int row, int col) {
            //在拘台上点击
            if (isOpenPlat) {
                Chess chess = getByCaptiveList(row, col);
                if (chess != null) chooseCaptive(chess);
            }
            //在棋盘上点击
            else {
                //已选中场上棋子时
                if (choose != null) {
                    //已选中传入底座时
                    if (transfer != null) {
                        if (transfer.getAfferentRange(choose).contains(room.getIndex(row, col))) {
                            afferentChess(row, col); //传入棋子
                        }
                        else {
                            cancelTransfer(); //取消传入底座的选取
                        }
                    }
                    //未选择传入时
                    else {
                        Chess newChess = room.getChessByPos(row, col);
                        //再点击空格
                        if (newChess == null) {
                            if (choose.getMoveRange().contains(room.getIndex(row, col))) {
                                moveChess(row, col); //移动选中棋子
                            }
                            else {
                                cancelChoose(); //取消选中棋子
                            }
                        }
                        //再点击己方棋子时
                        else if (newChess.side == side) {
                            if (choose.getTransferRange().contains(newChess.getIndex())) {
                                chooseTransfer(newChess); //选中传入底座
                            }
                            else {
                                chooseChess(newChess); //另选其它己方棋子
                            }
                        }
                        //再点击对方棋子时
                        else {
                            if (choose.getEatRange().contains(newChess.getIndex())) {
                                eatChess(newChess); //吃掉对方棋子
                            }
                            else {
                                cancelChoose(); //取消选中棋子
                            }
                        }
                    }
                }
                //已选中俘虏时
                else if (captive != null) {
                    //已经选择打入底座时
                    if (transfer != null) {
                        if (transfer.getPutRange(captive).contains(room.getIndex(row, col))) {
                            putChess(row, col); //打入棋子
                        }
                        else {
                            cancelPutTransfer(); //取消打入底座选取
                        }
                    }
                    //未选择打入时
                    else {
                        Chess newChess = room.getChessByPos(row, col);
                        //再点击己方棋子都可以当作打入底座
                        if (newChess != null && newChess.side == side) {
                            choosePutTransfer(newChess);
                        }
                        //再点击对方棋子或者空格
                        else {
                            cancelCaptive();
                        }
                    }
                }
                //未选中任何棋子时
                else {
                    Chess chess = room.getChessByPos(row, col);
                    if (chess != null && chess.side == side) {
                        chooseChess(chess);
                    }
                }
            }
        }

        //获取当前位置的俘虏棋子
        public Chess getByCaptiveList(int row, int col) {
            for (Chess chess : captiveList) {
                if (chess.getIndex() == room.getIndex(row, col)) {
                    return chess;
                }
            }
            return null;
        }

        //获取对方信息
        public Sider getOtherSider() {
            if (side == 1) return room.whiteSider;
            else return room.blackSider;
        }

        //选中棋子
        private void chooseChess(Chess choose) {
            this.captive = null;
            this.transfer = null;
            this.choose = choose;
            room.noticeAllRefreshGameInfo();
        }

        //选中俘虏
        private void chooseCaptive(Chess captive) {
            this.choose = null;
            this.transfer = null;
            this.captive = captive;
            switchPlat();
        }

        //选中传入台
        private void chooseTransfer(Chess transfer) {
            this.transfer = transfer;
            room.chessList.remove(choose); //传入棋子临时从场上离开（放到传送台的上面）
            room.noticeAllRefreshGameInfo();
        }

        //选中打入台
        private void choosePutTransfer(Chess transfer) {
            this.transfer = transfer;
            room.noticeAllRefreshGameInfo();
        }

        //取消场上棋子的选中
        private void cancelChoose() {
            this.transfer = null;
            this.choose = null;
            room.noticeAllRefreshGameInfo();
        }

        //取消俘虏的选中
        private void cancelCaptive() {
            this.transfer = null;
            this.captive = null;
            room.noticeAllRefreshGameInfo();
        }

        //取消传入台的选中
        private void cancelTransfer() {
            this.transfer = null;
            room.chessList.add(choose); //传入棋子从传送台上还原到场上
            room.noticeAllRefreshGameInfo();
        }

        //取消打入台的选中
        private void cancelPutTransfer(){
            this.transfer = null;
            room.noticeAllRefreshGameInfo();
        }

        //移动棋子
        private void moveChess(int row, int col) {
            //记录位置快照
            int oldRow = choose.row;
            int oldCol = choose.col;
            //尝试移动棋子
            choose.row = row;
            choose.col = col;
            //检查是否将帅面对面
            if(room.checkKingFaceKing()){
                //回滚快照
                choose.row = oldRow;
                choose.col = oldCol;
                //临时提示
                if (side == 1) room.player_black.sendMessage(Msger.broadcast, "该移动会导致将帅照面，已取消。");
                else room.player_white.sendMessage(Msger.broadcast, "该移动会导致将帅照面，已取消。");
                //取消选中棋子
                cancelChoose();
            }
            else {
                //回滚快照
                choose.row = oldRow;
                choose.col = oldCol;

                //#正式移动棋子
                //更新移动标记
                room.moveArrayList.clear();
                room.moveArrayList.add(new int[]{choose.getIndex(), room.getIndex(row, col)});
                //更新棋子坐标
                choose.row = row;
                choose.col = col;
                //移动过后选中状态取消
                choose = null;

                //检查回合是否结束（切换行动方）
                room.checkOver();
            }
        }

        //吃掉棋子
        private void eatChess(Chess target) {

            //记录位置快照
            int oldRow = choose.row;
            int oldCol = choose.col;
            //尝试移动棋子
            choose.row = target.row;
            choose.col = target.col;
            //是否直接吃王获胜
            boolean isWin = target instanceof General && getOtherSider().hp == 1;
            //检查是否将帅面对面
            if(!isWin && room.checkKingFaceKing()){
                //回滚快照
                choose.row = oldRow;
                choose.col = oldCol;
                //临时提示
                if (side == 1) room.player_black.sendMessage(Msger.broadcast, "该移动会导致将帅照面，已取消");
                else room.player_white.sendMessage(Msger.broadcast, "该移动会导致将帅照面，已取消");
                //取消选中棋子
                cancelChoose();
            }
            else {
                //回滚快照
                choose.row = oldRow;
                choose.col = oldCol;

                //更新移动标记
                room.moveArrayList.clear();
                room.moveArrayList.add(new int[]{choose.getIndex(), target.getIndex()});
                //被吃棋子是对方将帅的话 自己反而移出棋盘 对方将帅减少1命
                if (target instanceof General){
                    Sider otherSider = getOtherSider();
                    //对方有两命时
                    if (otherSider.hp > 1){
                        //对方王减少1命
                        otherSider.hp--;
                        //自己的棋子反而移出棋盘
                        room.chessList.remove(choose);
                        this.outside = choose;
                        choose = null;
                        room.checkOver();
                        return;
                    }
                }
                //被吃棋子移到拘台
                room.chessList.remove(target);
                captiveList.add(target);
                //更新棋子坐标
                choose.row = target.row;
                choose.col = target.col;
                //移动过后选中状态取消
                choose = null;
                //检查回合是否结束（切换行动方）
                room.checkOver();
            }
        }

        //传入棋子
        private void afferentChess(int row, int col) {
            //记录位置快照
            int oldRow = choose.row;
            int oldCol = choose.col;
            //尝试移动棋子
            choose.row = row;
            choose.col = col;
            room.chessList.add(choose);
            //检查是否将帅面对面
            if(room.checkKingFaceKing()){
                //回滚快照
                choose.row = oldRow;
                choose.col = oldCol;
                room.chessList.remove(choose);
                //临时提示
                if (side == 1) room.player_black.sendMessage(Msger.broadcast, "该移动会导致将帅照面，已取消");
                else room.player_white.sendMessage(Msger.broadcast, "该移动会导致将帅照面，已取消");
                //取消选中传入台
                cancelTransfer();
            }
            else {
                //回滚快照
                choose.row = oldRow;
                choose.col = oldCol;
                room.chessList.remove(choose);

                //更新移动标记
                room.moveArrayList.clear();
                room.moveArrayList.add(new int[]{choose.getIndex(), transfer.getIndex()});
                room.moveArrayList.add(new int[]{transfer.getIndex(), room.getIndex(row, col)});
                //传入棋子还原到棋盘上
                room.chessList.add(choose);
                //更新棋子坐标
                choose.row = row;
                choose.col = col;
                //传入过后取消选中状态
                transfer = null;
                choose = null;
                //检查回合是否结束（切换行动方）
                room.checkOver();
            }
        }

        //打入棋子
        private void putChess(int row, int col) {
            //更新移动标记
            room.moveArrayList.clear();
            room.moveArrayList.add(new int[]{transfer.getIndex(), room.getIndex(row, col)});
            //拘台棋子放到棋盘
            captiveList.remove(captive);
            captive.side = side; //打入棋子变成己方的
            captive.row = row;
            captive.col = col;
            room.chessList.add(captive); //被打入棋子添加到场上
            //打入过后取消选中状态
            transfer = null;
            captive = null;
            //检查回合是否结束（切换行动方）
            room.checkOver();
        }

    }

    /**
     * 棋子公共抽象类
     */
    private abstract static class Chess {

        public AfferentTwoLiveChessRoom room;
        public String name;
        public int side;
        public int row;
        public int col;

        public Chess(AfferentTwoLiveChessRoom room, String name, int side, int row, int col) {
            this.room = room;
            this.name = name;
            this.side = side;
            this.row = row;
            this.col = col;
        }

        //获取棋子的坐标索引
        public int getIndex() {
            return room.getIndex(row, col);
        }

        //获取前方
        protected int getFrontDirection() {
            if (side == 1) {
                return 1;
            }
            else if (side == 2) {
                return -1;
            }
            else {
                return 0;
            }
        }

        //判断自己是否在敌方半区
        protected boolean inEnemyBoard() {
            return isEnemyBoard(row, col);
        }

        //坐标点是否在敌方半区
        protected boolean isEnemyBoard(int row, int col) {
            if (side == 1){
                return row >= 5;
            }
            else {
                return row < 5;
            }
        }

        //位置是否是己方九宫格
        protected boolean isSelfPlace(int row, int col){
            if (side == 1){
                return row >= 0 && row <= 2 && col >= 3 && col <= 5;
            }
            else {
                return row >= 7 && row <= 9 && col >= 3 && col <= 5;
            }
        }

        //获取自身一周周围的格子（自身为中心“田”区，棋盘范围之外的不加入，最多8个格子）
        protected List<Integer> getAroundRange() {
            int[][] dxdys = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int x = row + dxdy[0];
                int y = col + dxdy[1];
                if (x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && room.curGrids[x][y] == 0) {
                    rangeIndex.add(room.getIndex(x, y));
                }
            }
            return rangeIndex;
        }

        //根据规则搜索棋子默认的移动范围
        protected List<Integer> defMoveRange(int[][] dxdys, int distance) {
            return defMoveRange(dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的移动范围
        protected List<Integer> defMoveRange(int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) { //否则遇到棋子阻碍就得停下
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                        continue;
                    }
                    if (skip >= mustJump) {
                        rangeIndex.add(room.getIndex(x, y));
                    }
                }
            }
            return rangeIndex;
        }

        //根据规则搜索棋子默认的吃子范围
        protected List<Integer> defEatRange(int[][] dxdys, int distance) {
            return defEatRange(dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的吃子范围
        protected List<Integer> defEatRange(int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) {
                        if (chess.side != this.side && skip >= mustJump) {
                            rangeIndex.add(room.getIndex(x, y));
                        }
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                    }
                }
            }
            return rangeIndex;
        }

        //根据规则搜索棋子默认的传送台范围
        protected List<Integer> defTransferRange(int[][] dxdys, int distance) {
            return defTransferRange(dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的传送台范围
        protected List<Integer> defTransferRange(int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) {
                        if (chess.side == this.side && skip >= mustJump) {
                            rangeIndex.add(room.getIndex(x, y));
                        }
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                    }
                }
            }
            return rangeIndex;
        }

        //根据规则搜索棋子默认的可传入空格范围
        protected List<Integer> defAfferentRange(Chess choose, int[][] dxdys, int distance) {
            return defAfferentRange(choose, dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的可传入空格范围
        protected List<Integer> defAfferentRange(Chess choose, int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    if (choose instanceof Bishop && isEnemyBoard(x, y)) break; //象不能传入到敌方半区
                    else if (choose instanceof Guard && !isSelfPlace(x, y)) break; //士不能传入到己方宫格外
                    else if (choose instanceof General && !isSelfPlace(x, y)) break; //将不能传入到己方宫格外
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) { //否则遇到棋子阻碍就得停下
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                        continue;
                    }
                    if (skip >= mustJump) {
                        if (x != choose.row || y != choose.col){ //选中棋子原来位置不能传入
                            rangeIndex.add(room.getIndex(x, y));
                        }
                    }
                }
            }
            return rangeIndex;
        }

        //根据规则搜索棋子默认的可打入落点空格范围
        protected List<Integer> defPutRange(Chess captive, int[][] dxdys, int distance) {
            return defPutRange(captive,dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的可打入落点空格范围
        protected List<Integer> defPutRange(Chess captive, int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    //if (captive instanceof Bishop && !isEnemyBoard(x, y)) continue; //象不能打入到己方半区
                    //else if (captive instanceof Guard && !isEnemyBoard(x, y)) continue; //士不能打入到己方半区
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) { //否则遇到棋子阻碍就得停下
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                        continue;
                    }
                    if (skip >= mustJump) {
                        if ((!(captive instanceof Bishop) || isEnemyBoard(x, y)) && (!(captive instanceof Guard) || isEnemyBoard(x, y))) { //士象不能打入到己方半区
                            rangeIndex.add(room.getIndex(x, y));
                        }
                    }
                }
            }
            return rangeIndex;
        }


        /**
         * 自定义 获取可移动空格范围
         */
        public abstract List<Integer> getMoveRange();

        /**
         * 自定义 获取可吃棋子范围
         */
        public abstract List<Integer> getEatRange();

        /**
         * 自定义 获取可选传送台棋子范围
         */
        public abstract List<Integer> getTransferRange();

        /**
         * 自定义 获取可传入空格范围
         */
        public abstract List<Integer> getAfferentRange(Chess choose);

        /**
         * 自定义 获取可打入落点空格范围
         */
        public abstract List<Integer> getPutRange(Chess captive);
    }

    /**
     * 帅/将
     */
    private static class General extends Chess {

        public General(AfferentTwoLiveChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            range.removeIf(i -> {
                int[] pos = room.getPositionByIndex(i);
                return !isSelfPlace(pos[0], pos[1]);
            });
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            range.removeIf(i -> {
                int[] pos = room.getPositionByIndex(i);
                return !isSelfPlace(pos[0], pos[1]);
            });
            // 白脸杀
            List<Integer> eatRange = defEatRange(new int[][]{{getFrontDirection(), 0}}, Integer.MAX_VALUE);
            for (int index : eatRange) {
                if (room.getChessByIndex(index) instanceof General) {
                    range.add(index);
                }
            }
            return range;
        }

        @Override
        public List<Integer> getTransferRange() {
            List<Integer> range = defTransferRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            range.removeIf(i -> {
                int[] pos = room.getPositionByIndex(i);
                return !isSelfPlace(pos[0], pos[1]);
            });
            return range;
        }

        @Override
        public List<Integer> getAfferentRange(Chess choose) {
            List<Integer> range = defAfferentRange(choose,new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            range.removeIf(i -> {
                int[] pos = room.getPositionByIndex(i);
                return !isSelfPlace(pos[0], pos[1]);
            });
            return range;
        }

        @Override
        public List<Integer> getPutRange(Chess captive) {
            List<Integer> range = defPutRange(captive, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, 1);
            range.removeIf(i -> {
                int[] pos = room.getPositionByIndex(i);
                return !isSelfPlace(pos[0], pos[1]);
            });
            return range;
        }
    }

    /**
     * 仕/士
     */
    private static class Guard extends Chess {
        public Guard(AfferentTwoLiveChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1);
            if (inEnemyBoard()){
                //士在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的士不能走出己方九宫
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isSelfPlace(pos[0], pos[1]);
                });
            }
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1);
            if (inEnemyBoard()){
                //士在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的士不能走出己方九宫
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isSelfPlace(pos[0], pos[1]);
                });
            }
            return range;
        }

        @Override
        public List<Integer> getTransferRange() {
            List<Integer> range = defTransferRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1);
            if (inEnemyBoard()){
                //士在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的士不能走出己方九宫
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isSelfPlace(pos[0], pos[1]);
                });
            }
            return range;
        }

        @Override
        public List<Integer> getAfferentRange(Chess choose) {
            List<Integer> range = defAfferentRange(choose, new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1);
            if (inEnemyBoard()){
                //士在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的士不能走出己方九宫
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isSelfPlace(pos[0], pos[1]);
                });
            }
            return range;
        }

        @Override
        public List<Integer> getPutRange(Chess captive) {
            List<Integer> range = defPutRange(captive,new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1);
            if (inEnemyBoard()){
                //士在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的士不能走出己方九宫
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isSelfPlace(pos[0], pos[1]);
                });
            }
            return range;
        }
    }

    /**
     * 相/象
     */
    private static class Bishop extends Chess {
        public Bishop(AfferentTwoLiveChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name,mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 2);
            range.removeAll(defMoveRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1));
            if (inEnemyBoard()){
                //在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的相不能走出己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return isEnemyBoard(pos[0], pos[1]);
                });
            }
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 2);
            range.removeAll(defEatRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1));
            if (inEnemyBoard()){
                //在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的相不能走出己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return isEnemyBoard(pos[0], pos[1]);
                });
            }
            return range;
        }

        @Override
        public List<Integer> getTransferRange() {
            List<Integer> range = defTransferRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 2);
            range.removeAll(defTransferRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1));
            if (inEnemyBoard()){
                //在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的相不能走出己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return isEnemyBoard(pos[0], pos[1]);
                });
            }
            return range;
        }

        @Override
        public List<Integer> getAfferentRange(Chess choose) {
            List<Integer> range = defAfferentRange(choose,new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 2);
            range.removeAll(defAfferentRange(choose,new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1));
            if (inEnemyBoard()){
                //在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的相不能走出己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return isEnemyBoard(pos[0], pos[1]);
                });
            }
            return range;
        }

        @Override
        public List<Integer> getPutRange(Chess captive) {
            List<Integer> range = defPutRange(captive,new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 2);
            range.removeAll(defPutRange(captive,new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, 1));
            if (inEnemyBoard()){
                //在敌方半场说明是打入进去的，不能走回己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return !isEnemyBoard(pos[0], pos[1]);
                });
            }
            else {
                //己方半场的相不能走出己方半场
                range.removeIf(i -> {
                    int[] pos = room.getPositionByIndex(i);
                    return isEnemyBoard(pos[0], pos[1]);
                });
            }
            return range;
        }
    }

    /**
     * 車/车
     */
    private static class Chariot extends Chess {
        public Chariot(AfferentTwoLiveChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            return defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }

        @Override
        public List<Integer> getEatRange() {
            return defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }

        @Override
        public List<Integer> getTransferRange() {
            return defTransferRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }

        @Override
        public List<Integer> getAfferentRange(Chess choose) {
            return defAfferentRange(choose,new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }

        @Override
        public List<Integer> getPutRange(Chess captive) {
            return defPutRange(captive,new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }
    }

    /**
     * 馬/马
     */
    private static class Horse extends Chess {
        public Horse(AfferentTwoLiveChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name,mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = new ArrayList<>();
            if (room.getChessByPos(row + 1, col) == null) {
                range.addAll(defMoveRange(new int[][]{{2, 1}, {2, -1}}, 1));
            }
            if (room.getChessByPos(row - 1, col) == null) {
                range.addAll(defMoveRange(new int[][]{{-2, 1}, {-2, -1}}, 1));
            }
            if (room.getChessByPos(row, col + 1) == null) {
                range.addAll(defMoveRange(new int[][]{{1, 2}, {-1, 2}}, 1));
            }
            if (room.getChessByPos(row, col - 1) == null) {
                range.addAll(defMoveRange(new int[][]{{1, -2}, {-1, -2}}, 1));
            }
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = new ArrayList<>();
            if (room.getChessByPos(row + 1, col) == null) {
                range.addAll(defEatRange(new int[][]{{2, 1}, {2, -1}}, 1));
            }
            if (room.getChessByPos(row - 1, col) == null) {
                range.addAll(defEatRange(new int[][]{{-2, 1}, {-2, -1}}, 1));
            }
            if (room.getChessByPos(row, col + 1) == null) {
                range.addAll(defEatRange(new int[][]{{1, 2}, {-1, 2}}, 1));
            }
            if (room.getChessByPos(row, col - 1) == null) {
                range.addAll(defEatRange(new int[][]{{1, -2}, {-1, -2}}, 1));
            }
            return range;
        }

        @Override
        public List<Integer> getTransferRange() {
            List<Integer> range = new ArrayList<>();
            if (room.getChessByPos(row + 1, col) == null) {
                range.addAll(defTransferRange(new int[][]{{2, 1}, {2, -1}}, 1));
            }
            if (room.getChessByPos(row - 1, col) == null) {
                range.addAll(defTransferRange(new int[][]{{-2, 1}, {-2, -1}}, 1));
            }
            if (room.getChessByPos(row, col + 1) == null) {
                range.addAll(defTransferRange(new int[][]{{1, 2}, {-1, 2}}, 1));
            }
            if (room.getChessByPos(row, col - 1) == null) {
                range.addAll(defTransferRange(new int[][]{{1, -2}, {-1, -2}}, 1));
            }
            return range;
        }

        @Override
        public List<Integer> getAfferentRange(Chess choose) {
            List<Integer> range = new ArrayList<>();
            if (room.getChessByPos(row + 1, col) == null) {
                range.addAll(defAfferentRange(choose, new int[][]{{2, 1}, {2, -1}}, 1));
            }
            if (room.getChessByPos(row - 1, col) == null) {
                range.addAll(defAfferentRange(choose, new int[][]{{-2, 1}, {-2, -1}}, 1));
            }
            if (room.getChessByPos(row, col + 1) == null) {
                range.addAll(defAfferentRange(choose, new int[][]{{1, 2}, {-1, 2}}, 1));
            }
            if (room.getChessByPos(row, col - 1) == null) {
                range.addAll(defAfferentRange(choose, new int[][]{{1, -2}, {-1, -2}}, 1));
            }
            return range;
        }

        @Override
        public List<Integer> getPutRange(Chess captive) {
            List<Integer> range = new ArrayList<>();
            if (room.getChessByPos(row + 1, col) == null) {
                range.addAll(defPutRange(captive, new int[][]{{2, 1}, {2, -1}}, 1));
            }
            if (room.getChessByPos(row - 1, col) == null) {
                range.addAll(defPutRange(captive, new int[][]{{-2, 1}, {-2, -1}}, 1));
            }
            if (room.getChessByPos(row, col + 1) == null) {
                range.addAll(defPutRange(captive, new int[][]{{1, 2}, {-1, 2}}, 1));
            }
            if (room.getChessByPos(row, col - 1) == null) {
                range.addAll(defPutRange(captive, new int[][]{{1, -2}, {-1, -2}}, 1));
            }
            return range;
        }
    }

    /**
     * 炮/砲
     */
    private static class Cannon extends Chess {
        public Cannon(AfferentTwoLiveChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            return defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }

        @Override
        public List<Integer> getEatRange() {
            return defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE, 1, 1);
        }

        @Override
        public List<Integer> getTransferRange() {
            return defTransferRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }

        @Override
        public List<Integer> getAfferentRange(Chess choose) {
            return defAfferentRange(choose, new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE, 1, 1);
        }

        @Override
        public List<Integer> getPutRange(Chess captive) {
            return defPutRange(captive,new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE, 1, 1);
        }
    }

    /**
     * 兵/卒
     */
    private static class Pawn extends Chess {
        public Pawn(AfferentTwoLiveChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            if (inEnemyBoard()) {
                return defMoveRange(new int[][]{{getFrontDirection(), 0}, {0, 1}, {0, -1}}, 1);
            }
            else {
                return defMoveRange(new int[][]{{getFrontDirection(), 0}}, 1);
            }
        }

        @Override
        public List<Integer> getEatRange() {
            if (inEnemyBoard()) {
                return defEatRange(new int[][]{{getFrontDirection(), 0}, {0, 1}, {0, -1}}, 1);
            }
            else {
                return defEatRange(new int[][]{{getFrontDirection(), 0}}, 1);
            }
        }

        @Override
        public List<Integer> getTransferRange() {
            if (inEnemyBoard()) {
                return defTransferRange(new int[][]{{getFrontDirection(), 0}, {0, 1}, {0, -1}}, 1);
            }
            else {
                return defTransferRange(new int[][]{{getFrontDirection(), 0}}, 1);
            }
        }

        @Override
        public List<Integer> getAfferentRange(Chess choose) {
            if (inEnemyBoard()) {
                return defAfferentRange(choose, new int[][]{{getFrontDirection(), 0}, {0, 1}, {0, -1}}, 1);
            }
            else {
                return defAfferentRange(choose, new int[][]{{getFrontDirection(), 0}}, 1);
            }
        }

        @Override
        public List<Integer> getPutRange(Chess captive) {
            if (inEnemyBoard()) {
                return defPutRange(captive, new int[][]{{getFrontDirection(), 0}, {0, 1}, {0, -1}}, 1);
            }
            else {
                return defPutRange(captive, new int[][]{{getFrontDirection(), 0}}, 1);
            }
        }

    }

}
